/*
 * BackupHandler.java
 *
 * Created on March 27, 2007, 9:37 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package edu.byu.isys413.group1E;

import edu.byu.isys413.group1E.data.*;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/** This is the Handler for the Backup processes.  A note about this is that since
 *we are renewing the backup service automatically based on batch processing, when a 
 *customer purchases a backup service, it's for a specified abount of time (i.e.,
 *6 months) from the purchase date.  The specific expiration date for the service is 
 *based on that criteria.
 *
 * @author tkulbeth
 */
public class BackupHandler {
    
    /**
     * Contains an instance of BackupHandler
     */
    private static BackupHandler instance = null;
    
    /**
     * Creates a new instance of BackupHandler
     */
    public BackupHandler() {
    }
    
    /**
     * Retrieves an instance of the BackupHandler object
     * 
     * @return instance of BackupHandler
     */
    public static synchronized BackupHandler getInstance() {
        if (instance == null) {
            instance = new BackupHandler();
        }
        return instance;
    }
    
    
    /** Creates a new backup revenue source that contains the information
     *needed from the GUI.
     */
    public synchronized BackupBO addNewBackup(String memberID, String buSize) throws Exception{
        BackupBO newBu = (BackupBO)BackupDAO.getInstance().create();
        MembershipBO memb = MembershipDAO.getInstance().read("00000110d80929f30000007f000002");
        double addSize = Double.parseDouble(buSize);
        if(memb.getBuExpDate() == null){  //set the backup variables in the membership object
            memb.setBuSize(10.0);
        }else{                          //set the backup size, keep the original backup expiration date
            double size = memb.getBuSize() + addSize;
            memb.setBuSize(size);
        }
        //get today's date for the begin date
        Calendar cal = Calendar.getInstance();
        Date today = cal.getTime();
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        String todayDate = fmt.format(today);
        //set the begin date
        memb.setBuExpDate(this.addNewPeriod(todayDate));
        newBu.setDescription("Backup for " + addSize + "G");
        newBu.setBeginDate(todayDate);
        newBu.setEndDate(memb.getBuExpDate());
        newBu.setBuSize(addSize);
        newBu.setPrice(this.calcPrice(addSize, memb.getBuExpDate()));
        MembershipDAO.getInstance().save(memb);
        return newBu;
    }
    
    
    /** Creates a new backup revenue source to renew the member's backup service according to the info in the
     * Membership object.
     */
    public synchronized BackupBO renewBackup(String memberID) throws Exception{
        BackupBO newBu = (BackupBO)BackupDAO.getInstance().create();
        MembershipBO memb = MembershipDAO.getInstance().read("00000110d80929f30000007f000002");
        String oldDate = memb.getBuExpDate();
        memb.setBuExpDate(this.addNewPeriod(memb.getBuExpDate()));
        newBu.setDescription("Renewal backup for " + memb.getBuSize() + "GB");
        newBu.setBeginDate(oldDate);
        newBu.setEndDate(memb.getBuExpDate());
        newBu.setPrice(this.calcPrice(memb.getBuSize(), memb.getBuExpDate()));        
        MembershipDAO.getInstance().save(memb);
        return newBu;
    }
    
    /** This is a method to update a backup RS that has been created, but not yet saved to the DB, which would 
     *occur if a customer purchased it, but then wanted to change the size of the backup purchase.
     *@param bu contains the backupBO to be updated
     *@param size contains the updated size of the backup (optional)
     *@param membershipID contains the membershipID (required)
     *@return updated backup object
     */
    public synchronized BackupBO updateBackup(BackupBO bu, String size, String memberID) throws Exception{
        MembershipBO memb = MembershipDAO.getInstance().read("00000110d80929f30000007f000002");
        double oldSize = bu.getBuSize();
        if(size != null){
            bu.setBuSize(Double.parseDouble(size));
        }
        //figure out how much the membership's buSize needs to be changed
        double curMembBuSize = memb.getBuSize();
        memb.setBuSize((curMembBuSize - oldSize) + bu.getBuSize());
        bu.setDescription("Updated backup for " + bu.getBuSize() + "GB");
        
//        System.out.println(memb.getBuSize());
        
        bu.setPrice(this.calcPrice(bu.getBuSize(), memb.getBuExpDate())); 
        MembershipDAO.getInstance().save(memb);
        return bu;        
    }
    
    /** Calculates the price for a Backup service revenue source
     *@param size contains the size of the backup
     *@param buExpDate contains the expiration date
     *@return price of the backup service revenue service
     */
    public double calcPrice(double size, String buExpDate){
        double price = 0.0;
        try {
            BackupServiceBO bs = BackupServiceDAO.getInstance().read();
            price = calcRemTime(buExpDate) * (bs.getCurBuPrice() * size);
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        }
        return price;
    }
    
    /** Calculates the time (in months) for a Backup service revenue source
     *to calculate charges with.
     *@param buExpDate contains the expiration date
     *@return months remaining for the backup service
     */
    public double calcRemTime(String buExpDate){
        double months = 0;
        try {
            BackupServiceBO bs = (BackupServiceBO)BackupServiceDAO.getInstance().read();
            //gets today's date
            Calendar cal = Calendar.getInstance();
            Date today = cal.getTime();
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
            String todayDate = fmt.format(today);
            
            //get the months and years
//            System.out.println(buExpDate);
            int expMonth;
            try {
                expMonth = Integer.parseInt(buExpDate.substring(5, 7));
            } catch (NumberFormatException ex) {
                expMonth = Integer.parseInt(buExpDate.substring(5,6));
            }
            int thisMonth;
            try {
                thisMonth = Integer.parseInt(todayDate.substring(5, 7));
            } catch (NumberFormatException ex) {
                thisMonth = Integer.parseInt(todayDate.substring(5,6));
            }
            int expYear = Integer.parseInt(buExpDate.substring(0,4));
            int thisYear = Integer.parseInt(todayDate.substring(0,4));
            if(expMonth >= thisMonth){
                //get the year difference
                months = (expMonth - thisMonth) + ((expYear - thisYear) * 12);
            }else{
                months = (12 - thisMonth) + expMonth + ((expYear - thisYear) * 12) - 12;
            }
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        }
        return months;
    }
    
    /** Adds the default period of 6 months to the current backup service.  This process is performed
     *whenever the renewal batch process is run and the backup is expiring.
     *@param now contains the start date for the new period that will be incremented.
     */
    public synchronized String addNewPeriod(String now) throws Exception{
        int PERIOD = 6;
        int thisDay = Integer.parseInt(now.substring(8,10));
        int thisMonth = Integer.parseInt(now.substring(5,7));
        int thisYear = Integer.parseInt(now.substring(0,4));
        if((thisMonth + PERIOD) > 12){
            thisYear++;
            thisMonth = (thisMonth + PERIOD) - 12;
        }else{
            thisMonth = thisMonth + PERIOD;
        }
        String newDate = "";
        newDate = newDate.concat(Integer.toString(thisYear).concat("-").concat(Integer.toString(thisMonth)).concat("-").concat(Integer.toString(thisDay)));
        return newDate;
    }
}
